#include "GeneralTextDocumentAdaptor.h"
#include "widget/Highlighter.h"

#include <QPlainTextDocumentLayout>
#include "QFile"
#include "QSaveFile"
#include "QFileInfo"
#include "QTextStream"

GeneralTextDocumentAdaptor::GeneralTextDocumentAdaptor()
{
    _document.setDocumentLayout(new QPlainTextDocumentLayout(&_document));
}

GeneralTextDocumentAdaptor::~GeneralTextDocumentAdaptor()
{
    if (_highlighter)
        delete _highlighter;
}

QString GeneralTextDocumentAdaptor::loadFile(const QString & fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) 
        return file.errorString();
    
    QTextStream in(&file);
    _document.setPlainText(in.readAll());
    _document.clearUndoRedoStacks();
    _document.setModified(false);
    return "";
}

QString GeneralTextDocumentAdaptor::saveFile(const QString &fileName)
{
    _save_flag = true;

    bool        backuped        = false;
    QString     backup_filename = fileName + ".bak";

    if (_save_backup_file) {
        if (QFile::exists(fileName))
            QFile::remove(backup_filename);

        backuped = QFile::copy(fileName, backup_filename);
        if(!backuped)
            qDebug() << "Fail to create backup for '" << fileName << "'";
    }

    QSaveFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text)) 
        return file.errorString();

    QTextStream out(&file);
    out.setCodec("UTF-8");
    out.setGenerateByteOrderMark(true);
    out << _document.toPlainText();
    if (!file.commit()) 
        return file.errorString();
    _document.setModified(false);

    return "";
}

bool GeneralTextDocumentAdaptor::wasSaved()
{
    if (_save_flag) {
        _save_flag = false;
        return true;
    }

    return false;
}

QString GeneralTextDocumentAdaptor::text()
{
    return _document.toPlainText();
}

bool GeneralTextDocumentAdaptor::setText(const QString &text)
{
    _document.setPlainText(text);
    _document.clearUndoRedoStacks();
    _document.setModified(false);
    return true;
}

bool GeneralTextDocumentAdaptor::isModified()
{
    return _document.isModified();
}

void GeneralTextDocumentAdaptor::setModified(bool modified)
{
    _document.setModified(modified);
}

void GeneralTextDocumentAdaptor::setHighlighter(Highlighter * highlighter)
{
    if (_highlighter)
        delete _highlighter;

    _highlighter = highlighter;
}

void GeneralTextDocumentAdaptor::publishDiagnostics(QVector<shell::Diagnostic> & diagnostics)
{
    _diagnostics.swap(diagnostics);
}

void GeneralTextDocumentAdaptor::semanticTokens(std::multimap<int,shell::SemanticToken> & tokens)
{
    _semantic_tokens.swap(tokens);
}

